home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / SAT / HeartQuest sample ƒ / gameWindow.p < prev    next >
Encoding:
Text File  |  1994-07-26  |  20.3 KB  |  698 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {=============== Game window handler ================}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { This file holds the game window and game menu handlers for HeartQuest.}
  10. { This is where most game-specific code goes, except for the code describing}
  11. { each object. }
  12.  
  13. { GameWindInit is called to initialize, which initializes the window and installs}
  14. {handler procedures (note that menus are installed in main.p). It calls the routines}
  15. {to initialize offscreen GrafPorts and all the animated objects. }
  16.  
  17. { When the user selects New Game, StartGame is called to set up a new}
  18. { game, and then MoveIt, the game driver routine is called. }
  19.  
  20. unit GameWind;
  21.  
  22. interface
  23.  
  24.     uses
  25.         transskel, SAT,{Globals, Other, Emergency, OffScreen, Animator, SATSound}
  26.         GameGlobals, sPlayer, sFlypaper, sHeart, sBonus, sPoints, scores, SoundConst, Sound;
  27.  
  28.     procedure DoGameMenu (item: integer);
  29.     procedure GameWindInit;
  30.     procedure DoGameOver;
  31.  
  32.  
  33. implementation
  34.  
  35. {var}
  36. {mp: MonsterPtr; { Bra att ha en global tillgänglig. Dvs praktiskt... }
  37. {    SlemtorksHandlerPtr: ProcPtr;}
  38.  
  39.     procedure InitSprites;
  40.     begin
  41. { Set up the two offscreen GrafPorts "gSAT.offScreen" and "gSAT.backScreen". SAT has a standard}
  42. { way to do this. Let SAT draw the background PICT for us, too. }
  43. {SetupOffAndBack(132, 129);}
  44.  
  45. { Call the init routines for each the sprite unit! Don't forget this! }
  46.         InitFlypaper;
  47.         InitHeart;
  48.         InitPlayer;
  49.         InitBonus;
  50.         InitPoints;
  51.     end;
  52.  
  53.     procedure DrawBackground;
  54.     forward;
  55.  
  56. { Setup a new level. This is called when the game starts ans at each new level.}
  57.     procedure SetupLevel (level: integer);
  58.         var
  59.             p: point;
  60.             i: integer;
  61.             mp, oldmp: SpritePtr;
  62.             r: rect;
  63.             s: Str255;
  64.             er: EventRecord; {For EventAvail}
  65.             strwidth: integer;
  66.  
  67. { A routine to create a bunch of hearts }
  68.         procedure MakeHearts (howmany: integer);
  69.             var
  70.                 i: integer;
  71.                 mp: SpritePtr;
  72.         begin
  73.             for i := 1 to howmany do
  74.                 case rand(4) of
  75.                     0: 
  76.                         mp := NewSprite(-2, Rand(gSAT.offSizeH - 112) + 17, 0, @SetupHeart);
  77.                     1: 
  78.                         mp := NewSprite(-2, Rand(gSAT.offSizeH - 112) + 17, gSAT.offSizeV - 32, @SetupHeart);
  79.                     2: 
  80.                         mp := NewSprite(-2, 0, Rand(gSAT.offSizeV - 32) + 17, @SetupHeart);
  81.                     3: 
  82.                         mp := NewSprite(-2, gSAT.offSizeH - xsize, Rand(gSAT.offSizeV - 32) + 17, @SetupHeart);
  83.                 end;
  84.         end;
  85.  
  86.     begin { SetupLevel }
  87.  
  88. { Clear the sprite list }
  89.         while gSAT.sRoot <> nil do
  90.             KillSprite(gSAT.sRoot);
  91.  
  92. { Create all the sprites for the level, depending on the level number. }
  93.         case level of
  94.             1: 
  95.                 begin
  96.                     batchcount := 6;
  97.                     bonus := 250;
  98.                     MakeHearts(6);
  99.                     mp := NewSprite(-3, 10, 10, @SetupFlypaper);
  100.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  101.                 end;
  102.             2: 
  103.                 begin
  104.                     batchcount := 10;
  105.                     bonus := 300;
  106.                     MakeHearts(10);
  107.                     mp := NewSprite(-3, 10, 10, @SetupFlypaper);
  108.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, 20, @SetupFlypaper);
  109.                     mp := NewSprite(-3, 20, gSAT.offSizeV - 32, @SetupFlypaper);
  110.                 end;
  111.             3: 
  112.                 begin
  113.                     batchcount := 12;
  114.                     MakeHearts(12);
  115.                     bonus := 350;
  116.                     mp := NewSprite(-3, 5, 5, @SetupFlypaper);
  117.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  118.                     mp := NewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  119.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  120.                 end;
  121.             4: 
  122.                 begin
  123.                     batchcount := 12;
  124.                     MakeHearts(12);
  125.                     bonus := 350;
  126.                     mp := NewSprite(-3, 5, 5, @SetupFlypaper);
  127.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  128.                     mp := NewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  129.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  130.                     mp := NewSprite(-3, 5, (gSAT.offSizeV - 32) mod 2, @SetupFlypaper);
  131.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, (gSAT.offSizeV - 32) mod 2, @SetupFlypaper);
  132.                 end;
  133.             5: 
  134.                 begin
  135.                     batchcount := 10;
  136.                     MakeHearts(10);
  137.                     bonus := 380;
  138.                     mp := NewSprite(-3, 5, 5, @SetupFlypaper);
  139.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  140.                     mp := NewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  141.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  142.                 end;
  143.             6: 
  144.                 begin
  145.                     batchcount := 12;
  146.                     MakeHearts(12);
  147.                     bonus := 420;
  148.                     mp := NewSprite(-3, 5, 5, @SetupFlypaper);
  149.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  150.                     mp := NewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  151.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  152.                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, (gSAT.offSizeV - 32) mod 2, @SetupFlypaper);
  153.                 end;
  154.             otherwise
  155.                 begin
  156.                     batchcount := level * 2;
  157.                     MakeHearts(level * 2);
  158.                     bonus := 300 + 20 * level;
  159.                     for i := 0 to level - 1 do
  160.                         begin
  161.                             case rand(6) of
  162.                                 0: 
  163.                                     mp := NewSprite(-3, 5, 5, @SetupFlypaper);
  164.                                 1: 
  165.                                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  166.                                 2: 
  167.                                     mp := NewSprite(-3, 5, 300, @SetupFlypaper);
  168.                                 3: 
  169.                                     mp := NewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  170.                                 4: 
  171.                                     mp := NewSprite(-3, (gSAT.offSizeH - xsize - 32) div 2, 5, @SetupFlypaper);
  172.                                 5: 
  173.                                     mp := NewSprite(-3, (gSAT.offSizeH - xsize - 32), gSAT.offSizeV - 32, @SetupFlypaper);
  174.                             end; { case }
  175.                         end;
  176.                 end;
  177.         end;
  178. { Reposition mouse to the center of the game area. }
  179.         p.h := 256;
  180.         p.v := 171;
  181.         SetMouse(p);
  182. { Make the player sprite. }
  183.         mp := NewSprite(2, (gSAT.offSizeH - xsize) div 2, gSAT.offSizeV div 2, @SetupPlayer);
  184. { Copy gSAT.backScreen to gSAT.offScreen to erase old sprites. }
  185.         CopyBits(gSAT.backScreen^.portBits, gSAT.offScreen^.portBits, gSAT.offScreen^.portRect, gSAT.offScreen^.portRect, srcCopy, nil);
  186.         PeekOffScreen; {replaces the following out-commented lines:}
  187.  
  188.         AddScore(0);
  189. { Do one frame of animation just to draw all the objects. }
  190.         RunSAT(false); {false or features^^.PlotFast; slow is ok - no hurry!}
  191.  
  192.         if level = 1 then
  193.             strwidth := StringWidth(MyGetIndString(startgameStrID))
  194.         else
  195.             strwidth := StringWidth(MyGetIndString(startlevelStrID));
  196.  
  197. { Draw a message and wait for click- this is a bit ugly. Consider other ways. }
  198.         SetPort(gSAT.wind);
  199.         SetRect(r, gSAT.offSizeH div 2 - strwidth div 2 - 5 + 2, gSAT.offSizeV div 2 + 35 + 2, gSAT.offSizeH div 2 + strwidth div 2 + 5 + 2, gSAT.offSizeV div 2 + 60 + 2); {offset by 2 pixels}
  200.         PaintRect(r);
  201.         SetRect(r, gSAT.offSizeH div 2 - strwidth div 2 - 5, gSAT.offSizeV div 2 + 35, gSAT.offSizeH div 2 + strwidth div 2 + 5, gSAT.offSizeV div 2 + 60);
  202.         EraseRect(r);
  203.  
  204.         MoveTo(gSAT.offSizeH div 2 - strwidth div 2, gSAT.offSizeV div 2 + 50);
  205.         if level = 1 then
  206.             DrawString(MyGetIndString(startgameStrID)) {str 16: Click the mouse to start the game.}
  207.         else
  208.             begin
  209.                 DrawString(MyGetIndString(startlevelStrID)); {str 17: Click the mouse to start level }
  210.                 NumToString(level, s);
  211.                 DrawString(s);
  212.                 DrawChar('.');
  213.             end;
  214.  
  215. {Wait until something happens}
  216.         FlushEvents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  217.         repeat
  218.         until EventAvail(mDownMask + keyDownMask, er);
  219.  
  220. { Redraw to get rid of the message we just made. }
  221.         PeekOffScreen;
  222.     end; { SetupLevel }
  223.  
  224. { Start a new game. Initialize level, score, number of lives, and call setuplevel to make the first level. }
  225.     procedure StartGame;
  226.     begin
  227.         ZeroScore;
  228.         Level := 1;
  229.  
  230.         setuplevel(level);
  231.     end;
  232.  
  233. { Game Over procedure. Draw "Game Over" text, check high scores. }
  234.  
  235.     procedure DoGameOver;
  236.         var
  237. { Variables for the Game Over-box }
  238.             theRect, theRect2: rect;
  239.             thePict: Handle;
  240.             bredd, i: integer;
  241.             dx, dy: integer;
  242.             time: longint;
  243.     begin
  244.         SetItem(GameMenu, Pause, MyGetIndString(pauseStrID)); {str 18: Pause}
  245. { Game Over display! }
  246.         SetPort(gSAT.wind);
  247.         if colorFlag and (gSAT.initDepth <> 1) then
  248.             thePICT := GetResource('PICT', 129)
  249.         else
  250.             thePICT := GetResource('PICT', 128);
  251.         theRect := PicHandle(thePICT)^^.picFrame;
  252.         theRect.right := theRect.right - theRect.left;
  253.         theRect.bottom := theRect.bottom - theRect.top;
  254.         theRect.top := 0;
  255.         theRect.left := 0;
  256.  
  257.         dx := (gSAT.offSizeH - (theRect.right - theRect.left)) div 2 - theRect.left;
  258.         dy := (gSAT.offSizeV - (theRect.bottom - theRect.top)) div 2 - theRect.top;
  259.         OffsetRect(theRect, dx, dy);
  260.  
  261.         bredd := theRect.right - theRect.left;
  262.         theRect2 := theRect;
  263.  
  264.         i := 1;
  265.         repeat
  266.             time := TickCount;
  267.             theRect.right := theRect2.right - bredd * (80 - i) div 160;
  268.             theRect.left := theRect2.left + bredd * (80 - i) div 160;
  269.             DrawPicture(PicHandle(thePICT), TheRect);
  270.             i := i + TickCount - time;
  271.         until i >= 80;
  272.  
  273.         SetPort(gSAT.offScreen);
  274.         DrawPicture(PicHandle(thePICT), TheRect);
  275.         SetPort(gSAT.wind);
  276.  
  277.         InvalRect(theRect);
  278.  
  279.         SATSoundShutUp; { Dispose of sound channel }
  280.  
  281.         FlushEvents(everyEvent, 0); { To forget events, like mouse clicks etc. }
  282.         ShowCursor;
  283.  
  284.         UpdateHigh; { Game over, was it high score? }
  285.     end;
  286.  
  287.  
  288. { This routine is the game driver. It calls the "Animator" package until the game ends or is paused. }
  289. { I also read the keyboard here. This could optionally be moved to the "player object" module. }
  290.  
  291.     procedure MoveIt;
  292.         var
  293.             fr, tr, r: Rect;
  294.             pt: Point;
  295.             h: Integer;
  296.             truepos: Longint;
  297. {n, x: Integer;    { Are these used? }
  298.             t, l: longint;
  299.             truepos32, bredd32: integer; { Some old bugfix that I no longer remember... }
  300.             truepos19, bredd19: integer;
  301.             theEvent: EventRecord; { för att testa musklick }
  302. { To check for key clicks with GetKeys:  - no longer used. km: KeyMap;}
  303.             hasEvent: Boolean;
  304.             ignore: OSerr;
  305.     begin
  306.         stillrunning := true; { A flag that tells whether or not to quit this routine. }
  307.  
  308.         HideCursor; { NOTE: No matter how we leave the MoveIt procedure, we should ShowCursor. }
  309.  
  310.         pt.h := 256;
  311.         pt.v := 171;
  312.         SetMouse(pt);
  313.  
  314. { Main loop! Keep running until the game is paused or ends. }
  315.         while stillrunning = true do
  316.             begin
  317.                 t := TickCount;
  318.                 SetPort(gSAT.wind);
  319.                 SetPort(gSAT.offScreen);
  320.  
  321. { Here is the real heart of the loop: call Animator once per loop. It will call all the objects. }
  322.                 RunSAT(features^^.plotFast);
  323. {SATSoundEvents; No longer needed - included in RunSAT!}
  324.  
  325. { All the rest of the main loop is game specific, next level, bonus handling, etc. }
  326.                 if (batchcount < 1) then
  327.                     begin
  328.                         SATSoundShutUp;
  329.                         if false then
  330.                             if features^^.sound then
  331.                                 ignore := SndPlay(nil, GetResource('snd ', SadarSnd), false);
  332.  
  333.                         SATSoundPlay(SadarSndH, 0, true);
  334.                         repeat
  335.                             SATSoundEvents
  336.                         until SATSoundDone;
  337.  
  338.                         if bonus > 0 then
  339.                             while bonus > 0 do
  340.                                 begin
  341.                                     Bonus := Bonus - 10;
  342. { SndPlay would have been ok here, since we want to play this synchronously.}
  343.  
  344.                                     SATSoundPlay(KlounkSndH, 0, true);
  345.                                     repeat
  346.                                         SATSoundEvents
  347.                                     until SATSoundDone;
  348.  
  349.                                     if false then
  350.                                         if features^^.sound then
  351.                                             ignore := SndPlay(nil, GetResource('snd ', KlounkSnd), false);
  352.  
  353.                                     if bonus < 0 then
  354.                                         begin
  355.                                             l := bonus;
  356.                                             bonus := 0;
  357.                                             AddScoreS(10 + l); {A special synchronous version of AddScore}
  358.                                         end
  359.                                     else
  360.                                         AddScoreS(10); { Bonus! }
  361.                                 end { if bonus > 0 }
  362.                         else if features^^.macho then
  363.                             stillrunning := false; { If no bonus, game over }
  364.  
  365.                         if (stillrunning and features^^.macho) or (level < 3) then {level < 4}
  366.                             begin
  367.                                 level := level + 1;
  368.                                 SetupLevel(level);
  369.                                 AddScoreS(0); {To update the level number}
  370.                             end
  371.                         else
  372.                             stillrunning := false;
  373.                     end; {if (batchcount < 1)}
  374.  
  375. { Check for keys being pressed }
  376.                 if features^^.allowBG then { if we are allowed to use the normal method }
  377.                     begin
  378.                         SystemTask;
  379. { Replaced the following call by WaitNextEvent if you want to be modern (but less backwards compatible). :-) }
  380.                         hasEvent := GetNextEvent(keyDownMask, theEvent)
  381.                     end
  382.                 else {Otherwise, use the faster GetOSEvent}
  383.                     begin
  384.                         hasEvent := GetOSEvent(keyDownMask, theEvent)
  385.                     end;
  386.  
  387. {If there was a keydown, see if it was one of the menu options that we support when running.}
  388.                 if hasEvent then { there was a keydown }
  389.                     if BitAnd(theEvent.modifiers, cmdKey) <> 0 then
  390.                         begin
  391.                             case char(BitAnd(theEvent.message, charCodeMask)) of
  392.                                 'p': 
  393.                                     begin
  394.                                         PauseFlag := true;
  395.                                         SATSoundShutUp; { Dispose of sound channel }
  396.                                         ShowCursor;
  397.                                         flushevents(6 + 8, 0); { In order to forget the cmd-p }
  398.                                         SetItem(GameMenu, Pause, MyGetIndString(resumeStrID)); {str 19: Resume}
  399.                                         exit(MoveIt);
  400.                                     end;
  401.                                 '.': 
  402.                                     StillRunning := false;
  403.                                 'q': 
  404.                                     begin
  405.                                         StillRunning := false;
  406.                                         SkelWhoa;
  407.                                     end;
  408.                                 's': 
  409.                                     begin
  410.                                         DoGameMenu(sound);
  411.                                     end;
  412.                                 otherwise
  413.                                     ;
  414.                             end; {case}
  415.                         end;
  416.  
  417. { Delay, using TickCount so it doesn't matter how fast our Mac is. }
  418.                 while ((TickCount - t) < 3) do
  419.                     ;
  420.  
  421.             end; { while stillrunning (main loop) }
  422.  
  423.         DoGameOver;
  424.  
  425.         FlushEvents(mouseDown + keyDown, 0); { In order to forget the cmd-p }
  426.     end;
  427.  
  428.  
  429. {We draw the background ourselves rather than using a simple backdrop PICT, to save space and to get the}
  430. {dithered background.}
  431.     procedure DrawBackground;
  432.         var
  433.             ph: PicHandle;
  434.             ignore: OSErr;
  435.             ramp: CTabHandle;
  436.             extraOff: CGrafPtr;
  437.             extraOffGD: GDHandle;
  438.             col: RGBColor;
  439.             thinr, r: Rect;
  440.             i, j: integer;
  441.  
  442.             posH, posV, scale, height, width: longint; {For scaling the trees}
  443.     begin
  444.         SATSetPortBackScreen;
  445.         SetRect(r, 0, 0, gSAT.offSizeH, gSAT.offSizeV);
  446.         if colorFlag then
  447.             begin
  448. {Draw our PICT under it.}
  449.                 if gSAT.initDepth = 1 then
  450.                     ph := GetPicture(133)
  451.                 else
  452.                     ph := GetPicture(132); {color PICT}
  453.                 if ph = nil then
  454.                     ReportStr(MyGetIndString(nopictStrID)); {STR 20: Can''t get PICT.}
  455.                 if ph <> nil then
  456.                     begin
  457.                         DrawPicture(ph, r);
  458.                         ReleaseResource(handle(ph));
  459.                     end;
  460. {Set up an 8 bit offscreen with a special color table, and ditherCopy to gSAT.backScreen.}
  461.                 ramp := GetCTable(128);
  462.                 if ramp = nil then
  463.                     ReportStr(MyGetIndString(noclutStrID)); {str 21. Can''t get CLUT 128.}
  464.                 if ramp <> nil then
  465.                     begin
  466.                         SetRect(thinr, 0, 0, 5, gSAT.offSizeV);
  467.                         ignore := CreateOffScreen(thinr, 8, ramp, extraOff, extraOffGD);
  468.                         if ignore <> noErr then
  469.                             ReportStr(MyGetIndString(nooffscreenStrID)); {str 22: Can''t make offscreen.}
  470.                         SetPort(GrafPtr(extraOff));
  471.                         SetGDevice(extraOffGD);
  472.                         PaintRect(extraOff^.portRect);
  473. {Make a scale of shades}
  474.                         for i := 0 to gSAT.offSizeV do
  475.                             begin
  476. {$PUSH}
  477. {$V-}
  478.                                 col.green := BSL(i, 16) div gSAT.offSizeV;
  479. {$POP}
  480.                                 col.red := col.green;
  481.                                 col.blue := col.green;
  482.                                 RGBForeColor(col);
  483.                                 MoveTo(0, i);
  484.                                 LineTo(5, i); {gSAT.offSizeH}
  485.                             end;
  486.  
  487.                         col.red := 0;
  488.                         col.green := 0;
  489.                         col.blue := 0;
  490.                         RGBForeColor(col);
  491.  
  492.                         r.top := gSAT.offSizeV div 4;
  493.                         thinr.top := gSAT.offSizeV div 4;
  494.  
  495.                         SATSetPortBackScreen;
  496.                         CopyBits(GrafPtr(extraOff)^.portBits, gSAT.backScreen^.portBits, thinr, r, srcCopy + ditherCopy, nil);
  497.                         DisposeOffscreen(extraOff, extraOffGD);
  498.  
  499.                     end;
  500.  
  501.             end
  502.         else
  503.             begin {This could just as well have been done by SAT}
  504.                 ph := GetPicture(133); {bw PICT}
  505.                 SATSetPortBackScreen;
  506.                 if ph <> nil then
  507.                     begin
  508.                         DrawPicture(ph, r);
  509.                         ReleaseResource(handle(ph));
  510.                     end;
  511.             end;
  512.  
  513. {Draw trees using PICTs!}
  514.  
  515. {First get the right PICT}
  516.         if gSAT.initDepth = 1 then
  517.             begin
  518.                 ph := GetPicture(135); {bw tree PICT}
  519.             end
  520.         else
  521.             begin
  522.                 ph := GetPicture(134); {color tree PICT}
  523.             end;
  524.  
  525. {Scale by ph^^.picframe}
  526.         for i := 0 to 10 do
  527. {For more trees: for j := i to 4 do}
  528.             begin
  529.                 posH := Rand(gSAT.offSizeH);
  530.                 posV := gSAT.offSizeV div 2 + longint(i) * i * gSAT.offSizeV div 300;
  531.  
  532.                 scale := (posV - gSAT.offSizeV div 4) div 17;
  533.                 height := scale * (ph^^.picframe.bottom - ph^^.picframe.top) div 40;
  534.                 width := scale * (ph^^.picframe.right - ph^^.picframe.left) div 40;
  535.  
  536.                 r.top := posV - height;
  537.                 r.bottom := posV;
  538.                 r.right := posH + width;
  539.                 r.left := posH;
  540.  
  541.                 DrawPicture(ph, r);
  542.             end;
  543.  
  544.         ReleaseResource(handle(ph));
  545.  
  546.         CopyBits(gSAT.backScreen^.portBits, gSAT.offScreen^.portBits, gSAT.backScreen^.portRect, gSAT.backScreen^.PortRect, srcCopy + ditherCopy, nil);
  547.         SATSetPortScreen;
  548.     end;
  549.  
  550.  
  551.     procedure GameWindUpdate;
  552.         var
  553.             s: str255;
  554.             r: Rect;
  555.             crsr: CursHandle;
  556.     begin
  557. {When the depth has changed, the game wind will get an update event,}
  558. {so let's give SAT a chance to update itself before updating!}
  559.  
  560.         crsr := GetCursor(WatchCursor);
  561.         SetCursor(crsr^^);
  562.         if SATDepthChangeTest then
  563.             begin
  564.                 DrawBackground;
  565.             end;
  566.         ReleaseResource(handle(crsr));
  567.         InitCursor;
  568.  
  569.         PeekOffScreen;
  570.         AddScore(0);
  571.     end;
  572.  
  573.     procedure DoGameMenu (item: integer);
  574.     begin
  575.         case (item) of
  576.             run: 
  577.                 begin
  578. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  579.                     if SATDepthChangeTest then {Update if necessary}
  580.                         DrawBackground;
  581.                     if not ((gSAT.initDepth = 1) or (gSAT.initDepth = 4) or (gSAT.initDepth = 8)) and features^^.PlotFast then
  582.                         begin
  583.                             reportstr(MyGetIndString(pleaseuncheckStrID));
  584. {str 23: Please uncheck ''Fast animation'' or set the monitor to 1-, 4- or 8-bit mode in the Control Panel.}
  585.                             exit(DoGameMenu);
  586.                         end;
  587.                     if pauseFlag then
  588.                         if QuestionStr(MyGetIndString(endStrID)) then {str 24: End the Current game?}
  589.                             DoGameMenu(abort)
  590.                         else
  591.                             exit(DoGameMenu);
  592.                     DisableItem(gameMenu, macho);
  593.                     ShowWindow(gSAT.wind);
  594.                     SelectWindow(gSAT.wind);
  595.                     StartGame;
  596.                     GameWindUpdate;
  597.                     MoveIt;
  598.                     if not pauseFlag then
  599.                         EnableItem(GameMenu, macho);
  600.                 end;
  601.             sound: 
  602.                 begin
  603.                     features^^.sound := not features^^.sound;
  604.                     CheckItem(GameMenu, sound, features^^.sound);
  605.                     if features^^.sound then { Tell the sound package our settings, so we don't have to bother. }
  606.                         SATSoundOn
  607.                     else
  608.                         SATSoundOff;
  609.                     ChangedResource(handle(features));
  610.                 end;
  611.             macho: 
  612.                 begin
  613.                     features^^.macho := not features^^.macho;
  614.                     CheckItem(GameMenu, macho, features^^.macho);
  615.                     ChangedResource(handle(features));
  616.                 end;
  617.             AllowBG: 
  618.                 begin
  619.                     features^^.AllowBG := not features^^.AllowBG;
  620.                     CheckItem(GameMenu, AllowBG, features^^.AllowBG);
  621.                     ChangedResource(handle(features));
  622.                 end;
  623.             FastAnimation: 
  624.                 begin
  625.                     features^^.PlotFast := not features^^.PlotFast;
  626.                     CheckItem(GameMenu, FastAnimation, features^^.PlotFast);
  627.                     ChangedResource(handle(features));
  628.                 end;
  629.             pause: 
  630.                 begin
  631. { Pause is only interesting here as "resume". }
  632.                     if pauseFlag then
  633.                         begin
  634. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  635.                             if SATDepthChangeTest then {Update if necessary}
  636.                                 DrawBackground;
  637.                             if not ((gSAT.initDepth = 1) or (gSAT.initDepth = 4) or (gSAT.initDepth = 8)) and features^^.PlotFast then
  638.                                 begin
  639.                                     ReportStr(MyGetIndString(pleaseuncheckStrID)); {str 23}
  640.                                     exit(DoGameMenu);
  641.                                 end;
  642.                             SetItem(GameMenu, pause, MyGetIndString(pauseStrID)); {str 18}
  643.                             pauseFlag := false;
  644.                             ShowWindow(gSAT.wind);
  645.                             SelectWindow(gSAT.wind);
  646.                             GameWindUpdate;
  647.                             MoveIt;
  648.                             if not pauseFlag then
  649.                                 EnableItem(GameMenu, macho);
  650.                         end;
  651.                 end;
  652.             abort: 
  653.                 begin
  654.                     if pauseFlag then
  655.                         begin
  656.                             SetItem(GameMenu, Pause, MyGetIndString(pauseStrID)); {str 18}
  657.                             DoGameOver;
  658.                             pauseFlag := false;
  659.                             EnableItem(GameMenu, macho);
  660.                         end
  661.                 end;
  662.         end;
  663.     end;
  664.  
  665.     procedure GameWindMouse (thePoint: Point; theTime: longint; theMods: integer; myProc: ProcPtr);
  666.     begin
  667.         if pauseFlag then
  668.             DoGameMenu(pause)
  669.         else
  670.             DoGameMenu(run);
  671.     end;
  672.  
  673.     procedure GameWindIdle;
  674.     begin
  675.     end;
  676.  
  677.     procedure GameWindClose;
  678.     begin
  679.     end;
  680.  
  681.     procedure GameWindInit;
  682.     begin
  683. { Tell TransSkel to handle all the tedious things with gSAT.wind. }
  684.         dummy := SkelWindow(gSAT.wind, @GameWindMouse, nil, @GameWindUpdate, nil, @GameWindClose, nil, @GameWindIdle, false);
  685.  
  686. { Initialize the sprites }
  687.         InitSprites;
  688.  
  689. {We draw the background ourselves in this game.}
  690.         DrawBackground;
  691.  
  692. { Draw the contents of the window (to give the user something to look at during the rest of startup). }
  693.         ShowWindow(gSAT.wind);
  694.         SelectWindow(gSAT.wind);
  695.         PeekOffScreen;
  696.     end;
  697.  
  698. end.